﻿#include "pch.h"
#include "canvas.h"
#include "engine/renderd2d.h"
#include "engine/text_render.hpp"
#include <common/winapi.h>
#include <common/mem_dc.h>
#include <element/font_pool.h>
#include <common/Exception.h>
#define ALPHA_OPAQUE		0xFF			///<透明度：不透明
#define ALPHA_TRANSPARENT	0x00			///<透明度：透明
namespace JOUI
{
	UICanvas::UICanvas(UIWnd* pWnd, size_t width, size_t height)
	{
		m_pWnd = pWnd;
		Resize(width, height);
	}
	UICanvas::~UICanvas()
	{
		if (m_clip_region) { ResetClip(); }
		SafeRelease(m_bitmap);
		m_bitmap = nullptr;
	}
	SIZE UICanvas::GetSize()
	{
		return m_size;
	}
	HRESULT UICanvas::Resize(size_t width, size_t height)
	{
		//不可以在绘制过程中调整画布大小
		handle_if_false(m_drawing == false, EE_NOREADY, L"不可以在绘制过程中调整画布大小");
		//参数默认处理
		if (width == 0) { width = 1; }
		if (height == 0) { height = 1; }
		SafeRelease(m_bitmap);

		//创建新的渲染目标位图
		handle_if_failed(
			g_d2d_dc->CreateBitmap(
				D2D1::SizeU(width, height), nullptr, 0,
				D2D1::BitmapProperties1(
					D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_GDI_COMPATIBLE,
					D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED),
					_SYS_DEFAULT_DPI, _SYS_DEFAULT_DPI, nullptr),
				&m_bitmap
			), L"创建渲染目标位图失败"
		);
		m_size = { (LONG)width, (LONG)height };
		return S_OK;
	}
	HRESULT UICanvas::GetClipRect(ExRectF* r_clip) const
	{
		CHECK_PARAM(r_clip);

		if (!m_clip_region) {
			*r_clip = {};
			return S_FALSE;
		}

		return m_clip_region->GetBounds(r_clip);
	}
	HRESULT UICanvas::GetClipRegion(UIRegion *r_clip_region) const
	{
		CHECK_PARAM(r_clip_region);
		if (!m_clip_region) { return S_FALSE; }
		return r_clip_region->CombineWithRegion(m_clip_region, RegionCombineMode::Copy);
	}
	HRESULT UICanvas::SetClipRect(float left, float top, float right, float bottom)
	{
		//必须在绘制过程中设置
		try
		{
			//如果已经有裁剪区域,则先清除
			if (m_clip_region) { throw_if_failed(ResetClip(), L"重置剪辑区失败"); }
			//创建新的裁剪区域对象(内部会做偏移)
			D2D1_RECT_F clip = D2D1Rect(left, top, right, bottom);
			m_clip_region = new UIRegion(clip.left, clip.top, clip.right, clip.bottom, true);
		
			//压入裁剪区域
			g_d2d_dc->PushAxisAlignedClip(D2D1Rect(left, top, right, bottom), g_d2d_dc->GetAntialiasMode());
			return S_OK;
		}
		catch_default({});
	}
	HRESULT UICanvas::SetClipRegion(UIRegion *clip_regioin)
	{
		try
		{
			//如果已经有裁剪区域,则先清除
			if (m_clip_region) { throw_if_failed(ResetClip(), L"重置剪辑区失败"); }

			if (clip_regioin) {

				m_clip_region = clip_regioin;
				//压入裁剪区域
				ID2D1Layer* layer = nullptr;
				throw_if_failed(g_d2d_dc->CreateLayer(&layer), L"创建层对象失败");

				g_d2d_dc->PushLayer(
					D2D1::LayerParameters(
						D2D1::InfiniteRect(),
						clip_regioin->m_geometry,
						g_d2d_dc->GetAntialiasMode()
					), layer
				);
				layer->Release();
			}

			return S_OK;
		}
		catch_default({});
	}
	HRESULT UICanvas::ResetClip()
	{
		//如果没有裁剪区域,则直接返回
		if (!m_clip_region) { return S_FALSE; }

		//否则根据裁剪区域类型进行处理
		if (m_clip_region->m_is_clip) {
			g_d2d_dc->PopAxisAlignedClip();
		}
		else {
			g_d2d_dc->PopLayer();
		}
		delete m_clip_region;
		m_clip_region = nullptr;
		return S_OK;
	}
	HRESULT UICanvas::GetTransform(ExMatrix* r_matrix)
	{
		CHECK_PARAM(r_matrix);

		//必须在绘制过程中

		//获取当前变换矩阵
		g_d2d_dc->GetTransform((D2D1_MATRIX_3X2_F*)r_matrix);
		return S_OK;
	}
	HRESULT UICanvas::SetTransform(const ExMatrix* matrix)
	{
		//必须在绘制过程中

		//设置变换矩阵
		D2D1_MATRIX_3X2_F tranform = MatrixEx(matrix);
		g_d2d_dc->SetTransform(tranform);
		return S_OK;
	}
	HRESULT UICanvas::GetDC(HDC* r_dc)
	{
		CHECK_PARAM(r_dc);

		//必须在绘制过程中
		if (m_pWnd->m_data.dx_counts > 0)
		{
			handle_if_false(g_d2d_gdiInterop, E_NOTIMPL, L"GDI兼容对象不存在");

			handle_if_failed(g_d2d_gdiInterop->GetDC(D2D1_DC_INITIALIZE_MODE_COPY, r_dc), L"获取DC失败");
		}
		return S_OK;
	}
	HRESULT UICanvas::ReleaseDC()
	{
		//必须在绘制过程中
		if (m_pWnd->m_data.dx_counts > 0)
		{
			handle_if_false(g_d2d_gdiInterop, EE_NOREADY, L"GDI兼容对象不存在");

			handle_if_failed(g_d2d_gdiInterop->ReleaseDC(nullptr), L"释放DC失败");
		}
		return S_OK;
	}
	HRESULT UICanvas::Flush()
	{
		handle_if_failed(g_d2d_dc->Flush(), L"刷新失败");
		return S_OK;
	}
	HRESULT UICanvas::ToImage(UIImage**dstImg, BOOL cdraw)
	{
		if (cdraw) { handle_if_failed(BeginDraw(), L"开始绘制画布失败"); }
		try
		{
			D2D1_BITMAP_PROPERTIES1 bp1 = D2D1::BitmapProperties1(
				D2D1_BITMAP_OPTIONS_CANNOT_DRAW | D2D1_BITMAP_OPTIONS_CPU_READ,
				D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED)
			);
			IWICBitmap* pWICBitmap = nullptr;
			ID2D1Bitmap1* pBitmap1 = nullptr;
			throw_if_failed(g_d2d_dc->CreateBitmap(D2D1::SizeU(m_size.cx, m_size.cy), NULL, 0, bp1, &pBitmap1), L"创建临时位图失败");
			throw_if_failed(pBitmap1->CopyFromBitmap(NULL, m_bitmap, NULL), L"从画布位图拷贝失败");
			D2D1_MAPPED_RECT mrc;
			throw_if_failed(pBitmap1->Map(D2D1_MAP_OPTIONS_READ, &mrc), L"锁住失败");
			throw_if_failed(g_wic_factory->CreateBitmap(m_size.cx, m_size.cy, GUID_WICPixelFormat32bppPBGRA, WICBitmapCacheOnDemand, &pWICBitmap), L"创建一个空目标位图失败");
			//锁定位图
			WICRect rect = { 0, 0, m_size.cx, m_size.cy };
			IWICBitmapLock* pLocker = NULL;
			throw_if_failed(pWICBitmap->Lock(&rect, WICBitmapLockWrite, &pLocker), L"锁定位图失败");
			LPBYTE aBits = NULL;
			UINT cbFrame = 0;
			UINT cbStride = 0;
			throw_if_failed(pLocker->GetDataPointer(&cbFrame, &aBits), L"获取缓冲区指针及行跨步失败");
			pLocker->GetStride(&cbStride);

			//拷贝点阵数据到WIC位图中
			cbStride = min(cbStride, mrc.pitch);
			for (UINT y = 0; y < (UINT)m_size.cy; y++)
			{
				RtlMoveMemory(aBits + cbStride * y, mrc.bits + mrc.pitch * y, cbStride);
			}
			//释放锁
			pLocker->Release();

			*dstImg = new UIImage(pWICBitmap);
			pBitmap1->Unmap();
			pBitmap1->Release();
			pWICBitmap->Release();
			if (cdraw) { throw_if_failed(EndDraw(), L"绘制过程出错"); }

			return S_OK;
		}
		catch_default({if (cdraw) { EndDraw(); }});
	}
	HRESULT UICanvas::BeginDraw()
	{
		if (m_pWnd->m_data.dx_counts == 0)
		{
			//开始绘制
			g_d2d_dc->BeginDraw();
		}
		//设置开始绘制标志
		m_drawing = true;
		InterlockedExchangeAdd((long*)&(m_pWnd->m_data.dx_counts), 1);
	
		//设置DC渲染目标位图
		g_d2d_dc->SetTarget(m_bitmap);


		//设置为标准变换矩阵
		g_d2d_dc->SetTransform(D2D1::Matrix3x2F::Identity());
		return S_OK;
	}
	HRESULT UICanvas::EndDraw()
	{
		//清除剪辑区
		ResetClip();
		//置空渲染目标位图
		g_d2d_dc->SetTarget(nullptr);

		//重置变换矩阵
		g_d2d_dc->SetTransform(D2D1::Matrix3x2F::Identity());
		if (InterlockedExchangeAdd((long*)&m_pWnd->m_data.dx_counts, -1) == 1)
		{
			//结束绘制
			HRESULT hr = g_d2d_dc->EndDraw();
			handle_if_failed(hr, L"绘制过程出现错误");
		}
		//标识当前未绘制状态
		m_drawing = false;
		return S_OK;
	}
	HRESULT UICanvas::Clear(UIColor color)
	{
		g_d2d_dc->Clear(color.GetDxObject());
		return S_OK;
	}
	HRESULT UICanvas::Clear(UIBrush *hBrush)
	{
		D2D1_COLOR_F lpColor{};
		hBrush->GetColor(lpColor);
		g_d2d_dc->Clear(lpColor);
		return S_OK;
	}
	ID2D1StrokeStyle* strokestyle_create(D2D1_CAP_STYLE startCap, D2D1_CAP_STYLE endCap, D2D1_CAP_STYLE dashCap, D2D1_LINE_JOIN lineJoin, FLOAT miterLimit, D2D1_DASH_STYLE dashStyle, FLOAT dashOffset)
	{
		INT nError = 0;
		D2D1_STROKE_STYLE_PROPERTIES pro = {};
		pro.startCap = startCap;
		pro.endCap = endCap;
		pro.dashCap = dashCap;
		pro.lineJoin = lineJoin;
		pro.miterLimit = miterLimit;
		pro.dashStyle = dashStyle;
		pro.dashOffset = dashOffset;
		ID2D1StrokeStyle* strokeStyle = nullptr;
		nError = g_d2d_factory->CreateStrokeStyle(pro, NULL, 0, &strokeStyle);
		return strokeStyle;
	}

	BOOL strokestyle_destroy(ID2D1StrokeStyle* hstrokestyle)
	{
		INT nError = 0;
		if (hstrokestyle != 0)
		{
			nError = hstrokestyle->Release();
		}
		return nError == 0;
	}
	HRESULT UICanvas::DrawPoint(UIBrush *hBrush, FLOAT x, FLOAT y, FLOAT strokeWidth, BOOL isRadius)
	{
		//坐标偏移
		_offset_(false, x, y);
		ID2D1StrokeStyle* stroke = strokestyle_create(
			isRadius ? D2D1_CAP_STYLE_ROUND : D2D1_CAP_STYLE_SQUARE,
			isRadius ? D2D1_CAP_STYLE_ROUND : D2D1_CAP_STYLE_SQUARE,
			isRadius ? D2D1_CAP_STYLE_ROUND : D2D1_CAP_STYLE_SQUARE,
			isRadius ? D2D1_LINE_JOIN_ROUND : D2D1_LINE_JOIN_MITER,
			1.0f,
			D2D1_DASH_STYLE_SOLID, 0);
		g_d2d_dc->DrawLine(D2D1::Point2F(x, y), D2D1::Point2F(x, y), (ID2D1Brush*)hBrush->GetContext(), strokeWidth, stroke);
		strokestyle_destroy(stroke);
		return S_OK;
	}
	HRESULT UICanvas::DrawLine(UIBrush *brush, float x1, float y1, float x2, float y2, float strokeWidth, DWORD strokeStyle, BOOL isRadius)
	{
		//坐标偏移
		_offset_(false, x1, y1, x2, y2);
		ID2D1StrokeStyle* stroke = strokestyle_create(
			isRadius ? D2D1_CAP_STYLE_ROUND : D2D1_CAP_STYLE_SQUARE,
			isRadius ? D2D1_CAP_STYLE_ROUND : D2D1_CAP_STYLE_SQUARE,
			isRadius ? D2D1_CAP_STYLE_ROUND : D2D1_CAP_STYLE_SQUARE,
			isRadius ? D2D1_LINE_JOIN_ROUND : D2D1_LINE_JOIN_MITER,
			1.0f,
			(D2D1_DASH_STYLE)strokeStyle, 0);
		//绘制直线
		g_d2d_dc->DrawLine(
			D2D1::Point2F(x1, y1), D2D1::Point2F(x2, y2),
			(ID2D1Brush*)brush->GetContext(), strokeWidth, stroke
		);
		strokestyle_destroy(stroke);
		return S_OK;
	}
	HRESULT UICanvas::DrawRect(UIBrush *brush, float left, float top,
		float right, float bottom, float strokeWidth, DWORD strokeStyle)
	{
		//坐标偏移
		_offset_(false, left, top);
		_offset_(true, right, bottom);
		//获取相关参数
		ID2D1StrokeStyle* stroke = strokestyle_create(
			D2D1_CAP_STYLE_SQUARE,
			D2D1_CAP_STYLE_SQUARE,
			D2D1_CAP_STYLE_SQUARE,
			D2D1_LINE_JOIN_MITER,
			1.0f,
			(D2D1_DASH_STYLE)strokeStyle, 0);
		//绘制矩形
		g_d2d_dc->DrawRectangle(
			D2D1Rect(left, top, right, bottom),
			(ID2D1Brush*)brush->GetContext(), strokeWidth, stroke
		);
		strokestyle_destroy(stroke);
		return S_OK;
	}
	HRESULT UICanvas::DrawEllipse(UIBrush *brush, float left, float top,
		float right, float bottom, float strokeWidth, DWORD strokeStyle)
	{
		ID2D1StrokeStyle* stroke = strokestyle_create(
			D2D1_CAP_STYLE_SQUARE,
			D2D1_CAP_STYLE_SQUARE,
			D2D1_CAP_STYLE_SQUARE,
			D2D1_LINE_JOIN_MITER,
			1.0f,
			(D2D1_DASH_STYLE)strokeStyle, 0);
	
		//绘制椭圆
		ExRectF rect = ExRectF(left, top, right, bottom).Normalize();
		g_d2d_dc->DrawEllipse(
			D2D1::Ellipse(
				D2D1::Point2F(rect.GetHorzCenter(), rect.GetVertCenter()),
				rect.Width() / 2, rect.Height() / 2
			), (ID2D1Brush*)brush->GetContext(), strokeWidth, stroke
		);
		strokestyle_destroy(stroke);
		return S_OK;
	}
	HRESULT UICanvas::DrawRoundRect(UIBrush *brush, float left, float top,
		float right, float bottom, float radius, float strokeWidth, DWORD strokeStyle)
	{
		//坐标偏移
		_offset_(false, left, top);
		_offset_(true, right, bottom);
		ID2D1StrokeStyle* stroke = strokestyle_create(
			D2D1_CAP_STYLE_ROUND,
			D2D1_CAP_STYLE_ROUND,
			D2D1_CAP_STYLE_ROUND,
			D2D1_LINE_JOIN_ROUND,
			1.0f,
			(D2D1_DASH_STYLE)strokeStyle, 0);
		//绘制圆角矩形
		g_d2d_dc->DrawRoundedRectangle(
			D2D1::RoundedRect(
				D2D1Rect(left, top, right, bottom), radius, radius
			), (ID2D1Brush*)brush->GetContext(), strokeWidth, stroke
		);
		strokestyle_destroy(stroke);
		return S_OK;
	}
	HRESULT UICanvas::DrawCustomRoundRect(UIBrush *brush, float left, float top,
		float right, float bottom, float radius_left_top, float radius_right_top,
		float radius_right_bottom, float radius_left_bottom, float strokeWidth, DWORD strokeStyle)
	{
		if (radius_left_top == 0 && radius_right_top == 0 && radius_right_bottom == 0 && radius_left_bottom == 0)
			return DrawRect(brush, left, top, right, bottom, strokeWidth);
		try
		{
			ID2D1StrokeStyle* stroke = strokestyle_create(
				D2D1_CAP_STYLE_SQUARE,
				D2D1_CAP_STYLE_SQUARE,
				D2D1_CAP_STYLE_SQUARE,
				D2D1_LINE_JOIN_MITER,
				1.0f,
				(D2D1_DASH_STYLE)strokeStyle, 0);
			//创建路径几何形
			ID2D1PathGeometry* geometry;
			throw_if_failed(
				g_d2d_factory->CreatePathGeometry(&geometry),
				L"创建路径几何形失败"
			);

			//生成圆角矩形路径
			ID2D1GeometrySink* sink;
			throw_if_failed(geometry->Open(&sink), L"开始描述路径失败");
			UIPath::MakeRoundRectFigure(sink, left, top, right, bottom,
				radius_left_top, radius_right_top, radius_right_bottom, radius_left_bottom, strokeWidth
			);
			throw_if_failed(sink->Close(), L"描述几何形路径错误");

			//绘制几何形
			g_d2d_dc->DrawGeometry(geometry, (ID2D1Brush*)brush->GetContext(), strokeWidth, stroke);
			strokestyle_destroy(stroke);
			geometry->Release();
			sink->Release();
			return S_OK;
		}
		catch_default({});
	}
	HRESULT UICanvas::DrawPath(UIBrush *brush, UIPath *path, float strokeWidth, DWORD strokeStyle, DWORD lineCap)
	{
		CHECK_PARAM(path);
		//获取相关参数
		ID2D1StrokeStyle* stroke = strokestyle_create(
			(D2D1_CAP_STYLE)lineCap,
			(D2D1_CAP_STYLE)lineCap,
			(D2D1_CAP_STYLE)lineCap,
			D2D1_LINE_JOIN_MITER,
			1.0f,
			(D2D1_DASH_STYLE)strokeStyle, 0);
		ID2D1Geometry* geometry = (ID2D1Geometry*)path->GetContext(0);

		//绘制几何形
		g_d2d_dc->DrawGeometry(geometry, (ID2D1Brush*)brush->GetContext(), strokeWidth, stroke);
		strokestyle_destroy(stroke);
		return S_OK;
	}
	HRESULT UICanvas::DrawPoly(UIBrush *hBrush, FLOAT left, FLOAT top, FLOAT right, FLOAT bottom, UINT NumberOfEdges, FLOAT Angle, FLOAT strokeWidth, UINT strokeStyle, DWORD lineCap)
	{
		CHECK_PARAM(hBrush);
		UIPath* path = new UIPath();
		path->BeginPath();
		path->AddPolygon(left, top, right, bottom, NumberOfEdges, Angle);
		path->EndPath();
		DrawPath(hBrush, path, strokeWidth, strokeStyle, lineCap);
		delete path;
		return S_OK;
	}
	HRESULT UICanvas::FillPoly(UIBrush *hBrush, FLOAT left, FLOAT top, FLOAT right, FLOAT bottom, UINT NumberOfEdges, FLOAT Angle)
	{
		CHECK_PARAM(hBrush);
		UIPath* path = new UIPath();
		path->BeginPath();
		path->AddPolygon(left, top, right, bottom, NumberOfEdges, Angle);
		path->EndPath();
		FillPath(hBrush, path);
		delete path;
		return S_OK;
	}
	HRESULT UICanvas::FillRect(UIBrush *brush, float left, float top,
		float right, float bottom)
	{
		CHECK_PARAM(brush);
		//坐标偏移
		_offset_(false, left, top);
		_offset_(true, right, bottom);
		//填充矩形
		g_d2d_dc->FillRectangle(D2D1Rect(left, top, right, bottom), (ID2D1Brush*)brush->GetContext());
		return S_OK;
	}
	HRESULT UICanvas::FillEllipse(UIBrush *brush, float left, float top,
		float right, float bottom)
	{
		CHECK_PARAM(brush);

		//填充椭圆
		ExRectF rect = ExRectF(left, top, right, bottom).Normalize();
		g_d2d_dc->FillEllipse(
			D2D1::Ellipse(
				D2D1::Point2F(rect.GetHorzCenter(), rect.GetVertCenter()),
				rect.Width() / 2, rect.Height() / 2
			), (ID2D1Brush*)brush->GetContext()
		);
		return S_OK;
	}
	HRESULT UICanvas::FillRoundRect(UIBrush *brush, float left, float top,
		float right, float bottom, float radius)
	{
		CHECK_PARAM(brush);
		_offset_(false, left, top);
		_offset_(true, right, bottom);
		//填充圆角矩形
		g_d2d_dc->FillRoundedRectangle(
			D2D1::RoundedRect(
				D2D1Rect(left, top, right, bottom), radius, radius
			), (ID2D1Brush*)brush->GetContext()
		);
		return S_OK;
	}
	HRESULT UICanvas::FillCustomRoundRect(UIBrush *brush, float left, float top,
		float right, float bottom, float radius_left_top, float radius_right_top, float radius_right_bottom, float radius_left_bottom)
	{
		if (radius_left_top == 0 && radius_right_top == 0 && radius_right_bottom == 0 && radius_left_bottom == 0)
			return FillRect(brush, left, top, right, bottom);
		CHECK_PARAM(brush);
		_offset_(false, left, top);
		_offset_(true, right, bottom);
		try
		{
			//创建路径几何形
			ID2D1PathGeometry* geometry;
			throw_if_failed(
				g_d2d_factory->CreatePathGeometry(&geometry),
				L"创建路径几何形失败"
			);

			//生成圆角矩形路径
			ID2D1GeometrySink* sink;
			throw_if_failed(geometry->Open(&sink), L"开始描述路径失败");
			UIPath::MakeRoundRectFigure(sink, left, top, right, bottom,
				radius_left_top, radius_right_top, radius_right_bottom, radius_left_bottom, 0
			);
			throw_if_failed(sink->Close(), L"描述几何形路径错误");

			//填充几何形
			g_d2d_dc->FillGeometry(geometry, (ID2D1Brush*)brush->GetContext());
			geometry->Release();
			sink->Release();
			return S_OK;
		}
		catch_default({});
	}
	HRESULT UICanvas::FillPath(UIBrush *brush, UIPath *path)
	{
		CHECK_PARAM(brush);
		CHECK_PARAM(path);
		ID2D1Geometry* geometry = (ID2D1Geometry*)path->GetContext(0);

		//填充几何形
		g_d2d_dc->FillGeometry(geometry, (ID2D1Brush*)brush->GetContext());
		return S_OK;
	}
	HRESULT UICanvas::FillRegion(UIBrush *brush, UIRegion *region)
	{
		CHECK_PARAM(brush);
		CHECK_PARAM(region);
		ID2D1Geometry* geometry = (ID2D1Geometry*)region->GetContext();

		//填充几何形
		g_d2d_dc->FillGeometry(geometry, (ID2D1Brush*)brush->GetContext());
		return S_OK;
	}
	HRESULT UICanvas::CalcTextSize(UIFont *font, LPCWSTR text, size_t text_length,
		DWORD text_format, float max_width, float max_height, float* r_width, float* r_height)
	{
		//默认参数处理
		if (max_width <= 0) { max_width = D2D1::FloatMax(); }
		if (max_height <= 0) { max_height = D2D1::FloatMax(); }

		try
		{
			//生成文本布局对象
			IDWriteTextLayout* layout = ToLayout(font, text, text_length,
				ExRectF(0, 0, max_width, max_height), text_format
			);
			if (!layout) { return S_FALSE; }

			//获得测量结果
			DWRITE_TEXT_METRICS tm;
			throw_if_failed(layout->GetMetrics(&tm), L"获取测量结果失败");

			//TODO:这里还需要额外处理文本效果带来的尺寸

			//返回结果
			if (r_width) { *r_width = tm.width; }
			if (r_height) { *r_height = tm.height; }
			layout->Release();
			return S_OK;
		}
		catch_default({});
	}
	HRESULT UICanvas::CalcTextWithIcon(UIFont *font, LPCWSTR text, size_t text_length,
		DWORD text_format, float left, float top, float right, float bottom, UIImage *icon_image, float icon_width, float icon_height,
		DWORD icon_pos, float split_size, ExRectF* r_text_rect, ExRectF* r_icon_rect, ExRectF* r_content_rect)
	{
		//获取整个范围
		ExRectF bounds_rect = ExRectF(left, top, right, bottom).Normalize();

		//获取图标真实尺寸
		D2D1_SIZE_U size{};
		if (icon_image)
		{
			icon_image->GetSize(size.width, size.height);
			//如果没有边界,则按绘制边界计算
			if (icon_width <= 0) { icon_width = bounds_rect.Width(); }
			if (icon_height <= 0) { icon_height = bounds_rect.Height(); }

			//如果超界,则限定一下
			icon_width = fabs(icon_width);
			icon_height = fabs(icon_height);
			if (size.width > icon_width) { size.width = (size_t)icon_width; }
			if (size.height > icon_height) { size.height = (size_t)icon_height; }
		}
		else {
			if (icon_width < 0) { size.width = -icon_width; }
			if (icon_height < 0) { size.height = -icon_height; }
		}

		//图标是否为水平位置
		BOOL is_horz = icon_pos == IconPos::Left || icon_pos == IconPos::Right;

		//获取文本真实尺寸
		float t_width = 0, t_height = 0;
		if (font && text)
		{
			//计算得到文本尺寸
			CalcTextSize(font, text, text_length, text_format,
				bounds_rect.Width() - is_horz ? size.width + split_size : 0,
				bounds_rect.Height() - is_horz ? 0 : size.height + split_size, &t_width, &t_height);
		}

		//计算内容区域尺寸
		ExPointF content_size;
		if (is_horz) {
			content_size.x = size.width + split_size + t_width;
			content_size.y = max(size.height, t_height);
		}
		else {
			content_size.x = max(size.width, t_width);
			content_size.y = size.height + split_size + t_height;
		}

		//计算内容矩形
		ExRectF rect;

		if (text_format & TextFormat::Center) {
			rect.left = bounds_rect.left + (bounds_rect.Width() - content_size.x) / 2;
			rect.right = rect.left + content_size.x;
		}
		else if (text_format & TextFormat::Right) {
			rect.right = bounds_rect.right;
			rect.left = rect.right - content_size.x;
		}
		else {
			rect.left = bounds_rect.left;
			rect.right = rect.left + content_size.x;
		}

		if (text_format & TextFormat::Middle) {
			rect.top = bounds_rect.top + (bounds_rect.Height() - content_size.y) / 2;
			rect.bottom = rect.top + content_size.y;
		}
		else if (text_format & TextFormat::Bottom) {
			rect.bottom = bounds_rect.bottom;
			rect.top = rect.bottom - content_size.y;
		}
		else {
			rect.top = bounds_rect.top;
			rect.bottom = rect.top + content_size.y;
		}

		//计算文本区域
		if (r_text_rect) {

			ExRectF text_bounds;

			//确定文本边界矩形
			if (icon_pos == IconPos::Left) {
				text_bounds = ExRectF(rect.left + size.width + split_size, rect.top, rect.right, rect.bottom);
			}
			else if (icon_pos == IconPos::Right) {
				text_bounds = ExRectF(rect.left, rect.top, rect.right - size.width - split_size, rect.bottom);
			}
			else if (icon_pos == IconPos::Top) {
				text_bounds = ExRectF(rect.left, rect.top + size.height + split_size, rect.right, rect.bottom);
			}
			else if (icon_pos == IconPos::Bottom) {
				text_bounds = ExRectF(rect.left, rect.top, rect.right, rect.bottom - size.height - split_size);
			}
			else { text_bounds = rect; }

			//计算得到文本真实矩形

			if (text_format & TextFormat::Center) {
				r_text_rect->left = text_bounds.left + (text_bounds.Width() - t_width) / 2;
				r_text_rect->right = r_text_rect->left + t_width;
			}
			else if (text_format & TextFormat::Right) {
				r_text_rect->right = text_bounds.right;
				r_text_rect->left = r_text_rect->right - t_width;
			}
			else {
				r_text_rect->left = text_bounds.left;
				r_text_rect->right = r_text_rect->left + t_width;
			}

			if (text_format & TextFormat::Middle) {
				r_text_rect->top = text_bounds.top + (text_bounds.Height() - t_height) / 2;
				r_text_rect->bottom = r_text_rect->top + t_height;
			}
			else if (text_format & TextFormat::Bottom) {
				r_text_rect->bottom = text_bounds.bottom;
				r_text_rect->top = r_text_rect->bottom - t_height;
			}
			else {
				r_text_rect->top = text_bounds.top;
				r_text_rect->bottom = r_text_rect->top + t_height;
			}
		}

		//计算图标区域
		if (r_icon_rect) {

			ExRectF icon_bounds;

			//确定图标边界矩形
			if (icon_pos == IconPos::Left) {
				icon_bounds = ExRectF(rect.left, rect.top, rect.left + size.width, rect.bottom);
			}
			else if (icon_pos == IconPos::Right) {
				icon_bounds = ExRectF(rect.right - size.width, rect.top, rect.right, rect.bottom);
			}
			else if (icon_pos == IconPos::Top) {
				icon_bounds = ExRectF(rect.left, rect.top, rect.right, rect.top + size.height);
			}
			else if (icon_pos == IconPos::Bottom) {
				icon_bounds = ExRectF(rect.left, rect.bottom - size.height, rect.right, rect.bottom);
			}
			else { icon_bounds = rect; }

			//计算得到图标真实矩形

			if (text_format & TextFormat::Center) {
				r_icon_rect->left = icon_bounds.left + (icon_bounds.Width() - size.width) / 2;
				r_icon_rect->right = r_icon_rect->left + size.width;
			}
			else if (text_format & TextFormat::Right) {
				r_icon_rect->right = icon_bounds.right;
				r_icon_rect->left = r_icon_rect->right - size.width;
			}
			else {
				r_icon_rect->left = icon_bounds.left;
				r_icon_rect->right = r_icon_rect->left + size.width;
			}

			if (text_format & TextFormat::Middle) {
				r_icon_rect->top = icon_bounds.top + (icon_bounds.Height() - size.height) / 2;
				r_icon_rect->bottom = r_icon_rect->top + size.height;
			}
			else if (text_format & TextFormat::Bottom) {
				r_icon_rect->bottom = icon_bounds.bottom;
				r_icon_rect->top = r_icon_rect->bottom - size.height;
			}
			else {
				r_icon_rect->top = icon_bounds.top;
				r_icon_rect->bottom = r_icon_rect->top + size.height;
			}
		}

		//赋值内容区域
		if (r_content_rect) { *r_content_rect = rect; }
		return S_OK;
	}
	HRESULT UICanvas::DeviceText(ID2D1DeviceContext* pContext, UIBrush* brush, UIFont* font, LPCWSTR text, size_t text_length, DWORD text_format, float left, float top, float right, float bottom)
	{
		CHECK_PARAM(font);
		bool clip = false;
		try
		{
			ExRectF rect = ExRectF(left, top, right, bottom).Normalize();

			IDWriteTextLayout* layout = ToLayout(
				font, text, text_length, rect, text_format
			);
			if (!layout) { return S_FALSE; }

			UITextRender render(pContext, brush);

			clip = !query_flags(text_format, TextFormat::NoClip);
			if (clip) { g_d2d_dc->PushAxisAlignedClip(Rect(rect), D2D1_ANTIALIAS_MODE_PER_PRIMITIVE); }

			throw_if_failed(
				layout->Draw(nullptr, &render, rect.left, rect.top),
				L"文本布局对象绘制失败"
			);

			if (clip) { g_d2d_dc->PopAxisAlignedClip(); }
			layout->Release();
			return S_OK;
		}
		catch_default({ if (clip) { g_d2d_dc->PopAxisAlignedClip(); } });
	}
	HRESULT UICanvas::StrokeText(UIBrush *brush, UIFont *font,
		LPCWSTR text, size_t text_length, DWORD text_format, float left, float top, float right, float bottom)
	{
		CHECK_PARAM(font);
		bool clip = false;
		try
		{
			ExRectF rect = ExRectF(left, top, right, bottom).Normalize();

			IDWriteTextLayout* layout = ToLayout(
				font, text, text_length, rect, text_format
			);
			if (!layout) { return S_FALSE; }

			UITextRender render(g_d2d_dc, brush);

			clip = !query_flags(text_format, TextFormat::NoClip);
			if (clip) { g_d2d_dc->PushAxisAlignedClip(Rect(rect), D2D1_ANTIALIAS_MODE_PER_PRIMITIVE); }

			throw_if_failed(
				layout->Draw(nullptr, &render, rect.left, rect.top),
				L"文本布局对象绘制失败"
			);

			if (clip) { g_d2d_dc->PopAxisAlignedClip(); }
			layout->Release();
			return S_OK;
		}
		catch_default({ if (clip) { g_d2d_dc->PopAxisAlignedClip(); } });
	}
	HRESULT UICanvas::FillText(UIBrush *brush, UIFont *font,
		LPCWSTR text, size_t text_length, DWORD text_format, float left, float top, float right, float bottom)
	{
		CHECK_PARAM(brush);
		CHECK_PARAM(font);
		bool clip = false;
		try
		{
			ExRectF rect = ExRectF(left, top, right, bottom).Normalize();

			IDWriteTextLayout* layout = ToLayout(
				font, text, text_length, rect, text_format
			);
			if (!layout) { return S_FALSE; }


			UITextRender render(g_d2d_dc, brush);

			clip = !query_flags(text_format, TextFormat::NoClip);
			if (clip) { g_d2d_dc->PushAxisAlignedClip(Rect(rect), D2D1_ANTIALIAS_MODE_PER_PRIMITIVE); }

			throw_if_failed(
				layout->Draw(nullptr, &render, rect.left, rect.top),
				L"文本布局对象绘制失败"
			);

			if (clip) { g_d2d_dc->PopAxisAlignedClip(); }
			layout->Release();
			return S_OK;
		}
		catch_default({ if (clip) { g_d2d_dc->PopAxisAlignedClip(); } });
	}
	HRESULT UICanvas::DrawTextByColor(UIFont *font, LPCWSTR text, size_t text_length,
		DWORD text_format, float left, float top, float right, float bottom, UIColor text_color, FLOAT *layoutWidth, FLOAT *layoutHeight)
	{
		CHECK_PARAM(font);
		bool clip = false;
		try
		{
			ExRectF rect = ExRectF(left, top, right, bottom).Normalize();

			//生成文本布局对象
			IDWriteTextLayout* layout(
				ToLayout(font, text, text_length, rect, text_format)
			);
			if (!layout) { return S_FALSE; }


			ID2D1SolidColorBrush* brush;
			throw_if_failed(
				g_d2d_dc->CreateSolidColorBrush(text_color.GetDxObject(), &brush),
				L"创建画刷失败"
			);
			//在 Windows 8.1 及更高版本中，如果由字体定义，则使用字形的颜色版本呈现文本。
			D2D1_DRAW_TEXT_OPTIONS options = g_dwMajorVersion ? D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT | D2D1_DRAW_TEXT_OPTIONS_CLIP : D2D1_DRAW_TEXT_OPTIONS_CLIP;
			clip = !query_flags(text_format, TextFormat::NoClip);
			if (clip) { g_d2d_dc->PushAxisAlignedClip(Rect(rect), D2D1_ANTIALIAS_MODE_PER_PRIMITIVE); }

			g_d2d_dc->DrawTextLayout(
				D2D1::Point2F(rect.left, rect.top),
				layout, brush, options
			);
			DWRITE_TEXT_METRICS Metrics = { 0 };
			layout->GetMetrics(&Metrics);
			if (layoutWidth)
				*layoutWidth = Metrics.widthIncludingTrailingWhitespace;
			if (layoutHeight)
				*layoutHeight = Metrics.height;

			if (clip) { g_d2d_dc->PopAxisAlignedClip(); }
			layout->Release();
			brush->Release();
			return S_OK;
		}
		catch_default({ if (clip) { g_d2d_dc->PopAxisAlignedClip(); } });
	}
	HRESULT UICanvas::DrawText(UIBrush *brush, UIFont *font,
		LPCWSTR text, size_t text_length, DWORD text_format,
		float left, float top, float right, float bottom)
	{
		CHECK_PARAM(brush);
		CHECK_PARAM(font);
		bool clip = false;
		try
		{
			ExRectF rect = ExRectF(left, top, right, bottom).Normalize();

			//生成文本布局对象
			IDWriteTextLayout* layout(
				ToLayout(font, text, text_length, rect, text_format)
			);
			if (!layout) { return S_FALSE; }


			clip = !query_flags(text_format, TextFormat::NoClip);
			if (clip) { g_d2d_dc->PushAxisAlignedClip(Rect(rect), D2D1_ANTIALIAS_MODE_PER_PRIMITIVE); }
			//在 Windows 8.1 及更高版本中，如果由字体定义，则使用字形的颜色版本呈现文本。
			D2D1_DRAW_TEXT_OPTIONS options = g_dwMajorVersion ? D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT | D2D1_DRAW_TEXT_OPTIONS_CLIP : D2D1_DRAW_TEXT_OPTIONS_CLIP;
			g_d2d_dc->DrawTextLayout(
				D2D1::Point2F(rect.left, rect.top),
				layout,
				(ID2D1Brush*)brush->GetContext(),
				options
			);

			if (clip) { g_d2d_dc->PopAxisAlignedClip(); }
			layout->Release();
			return S_OK;
		}
		catch_default({ if (clip) { g_d2d_dc->PopAxisAlignedClip(); } });
	}
	HRESULT UICanvas::DrawTextEx(UIBrush *brush, UIFont *font, LPCWSTR text, size_t text_length, DWORD text_format,
		float left, float top, float right, float bottom)
	{
		CHECK_PARAM(font);
		bool clip = false;
		try
		{
			ExRectF rect = ExRectF(left, top, right, bottom).Normalize();

			IDWriteTextLayout* layout = ToLayout(
				font, text, text_length, rect, text_format
			);
			if (!layout) { return S_FALSE; }


			UITextRender render(g_d2d_dc, brush);

			clip = !query_flags(text_format, TextFormat::NoClip);
			if (clip) { g_d2d_dc->PushAxisAlignedClip(Rect(rect), D2D1_ANTIALIAS_MODE_PER_PRIMITIVE); }

			throw_if_failed(
				layout->Draw(nullptr, &render, rect.left, rect.top),
				L"文本布局对象绘制失败"
			);

			if (clip) { g_d2d_dc->PopAxisAlignedClip(); }
			layout->Release();
			return S_OK;
		}
		catch_default({ if (clip) { g_d2d_dc->PopAxisAlignedClip(); } });
	}
	HRESULT UICanvas::DrawTextEffect(UIFont *font, LPCWSTR text, size_t text_length,
		DWORD text_format, float left, float top, float right, float bottom,
		DWORD effect_type, UIColor effect_color, LPARAM effect_param)
	{
		handle_ex(E_NOTIMPL, L"尚未实现");
	}
	HRESULT UICanvas::DrawTextAndEffect(UIBrush *brush, UIFont *font, LPCWSTR text, size_t text_length, DWORD text_format,
		float left, float top, float right, float bottom,
		DWORD effect_type, UIColor effect_color, LPARAM effect_param)
	{
		CHECK_PARAM(font);
		bool clip = false;
		try
		{
			ExRectF rect = ExRectF(left, top, right, bottom).Normalize();

			IDWriteTextLayout* layout = ToLayout(
				font, text, text_length, rect, text_format
			);
			if (!layout) { return S_FALSE; }


			UITextRender render(g_d2d_dc, brush);

			clip = !query_flags(text_format, TextFormat::NoClip);
			if (clip) { g_d2d_dc->PushAxisAlignedClip(Rect(rect), D2D1_ANTIALIAS_MODE_PER_PRIMITIVE); }

			throw_if_failed(
				layout->Draw(nullptr, &render, rect.left, rect.top),
				L"文本布局对象绘制失败"
			);

			//绘制效果
			//这里可能可以和TextRender组合

			if (clip) { g_d2d_dc->PopAxisAlignedClip(); }
			layout->Release();
			return S_OK;
		}
		catch_default({ if (clip) { g_d2d_dc->PopAxisAlignedClip(); } });
	}
	HRESULT UICanvas::DrawTextAndFontName(UIBrush* brush, LPCWSTR text, size_t text_length, DWORD text_format, float left, float top, float right, float bottom, LPCWSTR lpwzFontFace, INT dwFontSize, DWORD dwFontStyle)
	{
		bool clip = false;
		try
		{
			IDWriteTextFormat* pTextFormatArial = NULL;
			LONG lfWeight = 400;
			BYTE lfItalic = 0;
			if (dwFontStyle != 0)
			{
				lfWeight = ((dwFontStyle & FontStyle::Bold) == 0 ? 400 : 700);
				lfItalic = ((dwFontStyle & FontStyle::Italic) == 0 ? 0 : 2);
			}
			if (text_length == -1)
				text_length = _tcslen(text);
			throw_if_failed(g_dwrite_factory->CreateTextFormat(lpwzFontFace, nullptr,
				(DWRITE_FONT_WEIGHT)lfWeight, (DWRITE_FONT_STYLE)lfItalic, DWRITE_FONT_STRETCH_NORMAL,
				fScale(dwFontSize), L"en-US", &pTextFormatArial), L"文本布局对象绘制失败");
			//在 Windows 8.1 及更高版本中，如果由字体定义，则使用字形的颜色版本呈现文本。
			D2D1_DRAW_TEXT_OPTIONS options = g_dwMajorVersion ? D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT | D2D1_DRAW_TEXT_OPTIONS_CLIP : D2D1_DRAW_TEXT_OPTIONS_CLIP;
			g_d2d_dc->DrawTextW(
				text,
				text_length,
				pTextFormatArial,
				D2D1::RectF(left, top, right, bottom),
				(ID2D1Brush*)brush->GetContext(), options);

			pTextFormatArial->Release();

			if (clip) { g_d2d_dc->PopAxisAlignedClip(); }
			return S_OK;
		}
		catch_default({ if (clip) { g_d2d_dc->PopAxisAlignedClip(); } });
	}
	HRESULT OnDrawImage(UIImage *image, ExRectF& dst_rect, ExRectF& src_rect,
		DWORD mode, INT alpha, D2D1_INTERPOLATION_MODE interpolation, D2D1_INTERPOLATION_MODE m_interpolation_mode, INT radius)
	{
		//如果源矩形或目标矩形为空,则不绘制
		if (dst_rect.empty() || src_rect.empty()) { return S_FALSE; }
		//获得图像对象
		ID2D1Bitmap* bitmap = (ID2D1Bitmap*)image->GetContext();

		ID2D1ImageBrush* image_brush = nullptr;
		HRESULT hr = S_OK;
		//确定最终绘制的两个矩形,或者创建画刷
		switch (mode)
		{
		case ImageMode::Default: break;
		case ImageMode::ScaleFill: {

			//计算缩放比
			float width_ps = dst_rect.Width() / src_rect.Width();
			float height_ps = dst_rect.Height() / src_rect.Height();

			//取大的一个
			float scale_ps = max(width_ps, height_ps);

			//求最终源宽高
			width_ps = dst_rect.Width() / scale_ps;
			height_ps = dst_rect.Height() / scale_ps;

			//求最终源图矩形
			src_rect = ExRectF(
				src_rect.left + (src_rect.Width() - width_ps) / 2,
				src_rect.top + (src_rect.Height() - height_ps) / 2,
				width_ps,
				height_ps,
				true
			);
		}break;
		case ImageMode::ScaleCenter: {

			//计算缩放比
			float width_ps = dst_rect.Width() / src_rect.Width();
			float height_ps = dst_rect.Height() / src_rect.Height();

			//取小的一个,并约束其<=1
			float scale_ps = min(width_ps, height_ps);
			if (scale_ps > 1.0F) { scale_ps = 1.0F; }

			//求最终宽高
			width_ps = src_rect.Width() * scale_ps;
			height_ps = src_rect.Height() * scale_ps;

			//求最终目标矩形
			dst_rect = ExRectF(
				dst_rect.left + (dst_rect.Width() - width_ps) / 2,
				dst_rect.top + (dst_rect.Height() - height_ps) / 2,
				width_ps,
				height_ps,
				true
			);
		}break;
		case ImageMode::Tile:
		case ImageMode::Mirror:
		{
			UIImage* image_tmp = nullptr;
			image->Scale(dst_rect.Width(), dst_rect.Height(), &image_tmp);

			//确定扩展模式
			D2D1_EXTEND_MODE extend_mode = (mode == ImageMode::Tile) ? D2D1_EXTEND_MODE_WRAP : D2D1_EXTEND_MODE_MIRROR;
			//创建图像画刷
			hr = g_d2d_dc->CreateImageBrush((ID2D1Bitmap*)image_tmp->GetContext(),
				D2D1::ImageBrushProperties(
					D2D1::RectF(src_rect.left, src_rect.top, src_rect.right, src_rect.bottom),
					extend_mode, extend_mode
				), &image_brush
			);
			delete image_tmp;
		}break;
		case ImageMode::LeftTop: {
			dst_rect.right = dst_rect.left + src_rect.Width();
			dst_rect.bottom = dst_rect.top + src_rect.Height();
		}break;
		case ImageMode::CenterTop: {
			float width = src_rect.Width();
			dst_rect.left += (dst_rect.Width() - width) / 2;
			dst_rect.right = dst_rect.left + width;

			dst_rect.bottom = dst_rect.top + src_rect.Height();
		}break;
		case ImageMode::RightTop: {
			dst_rect.left = dst_rect.right - src_rect.Width();
			dst_rect.bottom = dst_rect.top + src_rect.Height();
		}break;
		case ImageMode::LeftMiddle: {
			dst_rect.right = dst_rect.left + src_rect.Width();

			float height = src_rect.Height();
			dst_rect.top += (dst_rect.Height() - height) / 2;
			dst_rect.bottom = dst_rect.top + height;
		}break;
		case ImageMode::CenterMiddle: {
			float width = src_rect.Width();
			dst_rect.left += (dst_rect.Width() - width) / 2;
			dst_rect.right = dst_rect.left + width;

			float height = src_rect.Height();
			dst_rect.top += (dst_rect.Height() - height) / 2;
			dst_rect.bottom = dst_rect.top + height;
		}break;
		case ImageMode::RightMiddle: {
			dst_rect.left = dst_rect.right - src_rect.Width();

			float height = src_rect.Height();
			dst_rect.top += (dst_rect.Height() - height) / 2;
			dst_rect.bottom = dst_rect.top + height;
		}break;
		case ImageMode::LeftBottom: {
			dst_rect.right = dst_rect.left + src_rect.Width();
			dst_rect.top = dst_rect.bottom - src_rect.Height();
		}break;
		case ImageMode::CenterBottom: {
			float width = src_rect.Width();
			dst_rect.left += (dst_rect.Width() - width) / 2;
			dst_rect.right = dst_rect.left + width;

			dst_rect.top = dst_rect.bottom - src_rect.Height();
		}break;
		case ImageMode::RightBottom: {
			dst_rect.left = dst_rect.right - src_rect.Width();
			dst_rect.top = dst_rect.bottom - src_rect.Height();
		}break;
		default: handle_ex(E_NOTIMPL, L"不支持的绘制模式");
		}

		//判断上面执行的没问题
		handle_if_failed(hr, L"绘制图像失败");

		//默认插值模式
		if (interpolation == D2D1_INTERPOLATION_MODE_FORCE_DWORD) {
			interpolation = m_interpolation_mode;
		}

		//如果有画刷则填充画刷,否则绘制图像
		if (image_brush) {
			image_brush->SetOpacity(alpha / 255.0F);
			image_brush->SetTransform(D2D1::Matrix3x2F::Translation(dst_rect.left, dst_rect.top));
			if (radius == 0)
				g_d2d_dc->FillRectangle(D2D1::RectF(dst_rect.left, dst_rect.top, dst_rect.right, dst_rect.bottom), image_brush);
			else
			{
				D2D1_ROUNDED_RECT rect = { dst_rect.left, dst_rect.top, dst_rect.right, dst_rect.bottom };
				rect.radiusX = radius;
				rect.radiusY = radius;
				g_d2d_dc->FillRoundedRectangle(rect, image_brush);
			}
			image_brush->Release();
		}
		else {
			g_d2d_dc->DrawBitmap(bitmap,
				D2D1::RectF(dst_rect.left, dst_rect.top, dst_rect.right, dst_rect.bottom),
				alpha / 255.0F, interpolation,
				D2D1::RectF(src_rect.left, src_rect.top, src_rect.right, src_rect.bottom)
			);
		}

		return S_OK;
	}
	HRESULT UICanvas::DrawImage(UIImage* image, float left, float top, INT alpha)
	{
		if (image)
		{
			if (alpha == 0) { return S_FALSE; }

			//计算两个矩形
			D2D1_SIZE_F size = ((ID2D1Bitmap*)image->GetContext())->GetSize();
			ExRectF dst_rect(left, top, size.width, size.height, true);
			ExRectF src_rect(0, 0, size.width, size.height);

			return OnDrawImage(image, dst_rect, src_rect, ImageMode::Default, alpha, D2D1_INTERPOLATION_MODE_FORCE_DWORD, m_interpolation_mode, 0);
		}
		return S_FALSE;
	}
	HRESULT UICanvas::DrawImageRect(UIImage *image, float left, float top,
		float right, float bottom, ImageMode mode, INT alpha, INT radius)
	{
		CHECK_PARAM(image);
		//计算两个矩形
		D2D1_SIZE_F size = ((ID2D1Bitmap*)image->GetContext())->GetSize();
		ExRectF dst_rect = ExRectF(left, top, right, bottom).Normalize();
		ExRectF src_rect(0, 0, size.width, size.height);
		return OnDrawImage(image, dst_rect, src_rect, mode, alpha, D2D1_INTERPOLATION_MODE_FORCE_DWORD, m_interpolation_mode, radius);
	}
	HRESULT UICanvas::DrawImagePart(UIImage *image, float left, float top,
		float src_left, float src_top, float src_right, float src_bottom, INT alpha)
	{
		CHECK_PARAM(image);
		if (alpha == 0) { return S_FALSE; }

		//计算两个矩形
		ExRectF src_rect = ExRectF(src_left, src_top, src_right, src_bottom).Normalize();
		ExRectF dst_rect(left, top, src_rect.Width(), src_rect.Height());

		return OnDrawImage(image, dst_rect, src_rect, ImageMode::Default, alpha, D2D1_INTERPOLATION_MODE_FORCE_DWORD, m_interpolation_mode, 0);
	}
	HRESULT UICanvas::DrawImagePartRect(UIImage *image, float left, float top,
		float right, float bottom, float src_left, float src_top, float src_right, float src_bottom,
		ImageMode mode, INT alpha, INT radius)
	{
		CHECK_PARAM(image);
		if (alpha == 0) { return S_FALSE; }
		//计算两个矩形
		ExRectF src_rect = ExRectF(src_left, src_top, src_right, src_bottom).Normalize();
		ExRectF dst_rect = ExRectF(left, top, right, bottom).Normalize();

		return OnDrawImage(image, dst_rect, src_rect, mode, alpha, D2D1_INTERPOLATION_MODE_FORCE_DWORD, m_interpolation_mode, radius);
	}
	HRESULT UICanvas::DrawGridsImage(UIImage *image, float left, float top,
		float right, float bottom, info_GridsImage* grids, INT alpha)
	{
		CHECK_PARAM(image);
		CHECK_PARAM(grids);
		if (alpha == 0) { return S_FALSE; }
		D2D1_SIZE_U size{};
		image->GetSize(size.width, size.height);

		return DrawGridsImagePart(image, left, top, right, bottom,
			0, 0, size.width, size.height,
			grids, alpha
		);
	}

	inline ImageMode _gflag_to_imode(DWORD flags, int pos)
	{
		flags = (flags >> pos) & 0x0F;
		return flags == 0 ? ImageMode::Default :
			flags & GridsImageMode::LeftNone ? (ImageMode)-1 :
			flags & GridsImageMode::LeftTile ? ImageMode::Tile :
			flags & GridsImageMode::LeftMirror ? ImageMode::Mirror :
			ImageMode::Default;
	}

	HRESULT UICanvas::DrawGridsImagePart(UIImage *image, float left, float top,
		float right, float bottom, float src_left, float src_top, float src_right, float src_bottom,
		info_GridsImage* grids, INT alpha)
	{
		CHECK_PARAM(image);
		CHECK_PARAM(grids);
		if (alpha == 0) { return S_FALSE; }


		//生成两个矩形,如果其中有的为空,则不绘制
		ExRectF dst_rect = ExRectF(left, top, right, bottom).Normalize();
		ExRectF src_rect = ExRectF(src_left, src_top, src_right, src_bottom).Normalize();
		if (dst_rect.empty()) { return S_FALSE; }
		if (src_rect.empty()) { return S_FALSE; }

		//生成两个中心块矩形[5]
		ExRectF src_rect_b5(
			src_rect.left + grids->left,
			src_rect.top + grids->top,
			src_rect.right - grids->right,
			src_rect.bottom - grids->bottom
		);
		ExRectF dst_rect_b5(
			dst_rect.left + grids->left,
			dst_rect.top + grids->top,
			dst_rect.right - grids->right,
			dst_rect.bottom - grids->bottom
		);

		//如果源中心块为空,则不绘制
		if (src_rect_b5.empty()) { return S_FALSE; }

		ExRectF src_block_rect{};
		ExRectF dst_block_rect{};
		ImageMode mode = ImageMode::Default;

		D2D1_INTERPOLATION_MODE interpolation_mode = D2D1_INTERPOLATION_MODE_HIGH_QUALITY_CUBIC;

		//绘制[5]
		if ((grids->flags & GridsImageMode::CenterNone) == 0)
		{
			src_block_rect = src_rect_b5;
			dst_block_rect = dst_rect_b5;
			mode = _gflag_to_imode(grids->flags, 4);
			OnDrawImage(image, dst_block_rect, src_block_rect, mode, alpha, interpolation_mode, m_interpolation_mode, 0);
		}

		//不是垂直三宫图,绘制[4][6]
		if (!float_eq(src_rect_b5.Width(), src_rect.Width()))
		{
			//绘制[4]
			if ((grids->flags & GridsImageMode::LeftNone) == 0)
			{
				src_block_rect = ExRectF(src_rect.left, src_rect_b5.top, src_rect_b5.left, src_rect_b5.bottom);
				dst_block_rect = ExRectF(dst_rect.left, dst_rect_b5.top, dst_rect_b5.left, dst_rect_b5.bottom);
				mode = _gflag_to_imode(grids->flags, 0);
				OnDrawImage(image, dst_block_rect, src_block_rect, mode, alpha, interpolation_mode, m_interpolation_mode,0);
			}

			//绘制[6]
			if ((grids->flags & GridsImageMode::RightNone) == 0)
			{
				src_block_rect = ExRectF(src_rect_b5.right, src_rect_b5.top, src_rect.right, src_rect_b5.bottom);
				dst_block_rect = ExRectF(dst_rect_b5.right, dst_rect_b5.top, dst_rect.right, dst_rect_b5.bottom);
				mode = _gflag_to_imode(grids->flags, 2);
				OnDrawImage(image, dst_block_rect, src_block_rect, mode, alpha, interpolation_mode, m_interpolation_mode,0);
			}
		}

		//不是水平三宫图,绘制[2][8]
		if (!float_eq(src_rect_b5.Height(), src_rect.Height()))
		{
			//绘制[8]
			if ((grids->flags & GridsImageMode::TopNone) == 0)
			{
				src_block_rect = ExRectF(src_rect_b5.left, src_rect.top, src_rect_b5.right, src_rect_b5.top);
				dst_block_rect = ExRectF(dst_rect_b5.left, dst_rect.top, dst_rect_b5.right, dst_rect_b5.top);
				mode = _gflag_to_imode(grids->flags, 1);
				OnDrawImage(image, dst_block_rect, src_block_rect, mode, alpha, interpolation_mode, m_interpolation_mode,0);
			}

			//绘制[2]
			if ((grids->flags & GridsImageMode::BottomNone) == 0)
			{
				src_block_rect = ExRectF(src_rect_b5.left, src_rect_b5.bottom, src_rect_b5.right, src_rect.bottom);
				dst_block_rect = ExRectF(dst_rect_b5.left, dst_rect_b5.bottom, dst_rect_b5.right, dst_rect.bottom);
				mode = _gflag_to_imode(grids->flags, 3);
				OnDrawImage(image, dst_block_rect, src_block_rect, mode, alpha, interpolation_mode, m_interpolation_mode,0);
			}
		}

		//不是三宫图则绘制[1][3][7][9]
		if (!float_eq(src_rect_b5.Height(), src_rect.Height()) && !float_eq(src_rect_b5.Width(), src_rect.Width()))
		{
			mode = ImageMode::Default;

			//绘制[7]
			src_block_rect = ExRectF(src_rect.left, src_rect.top, src_rect_b5.left, src_rect_b5.top);
			dst_block_rect = ExRectF(dst_rect.left, dst_rect.top, dst_rect_b5.left, dst_rect_b5.top);
			OnDrawImage(image, dst_block_rect, src_block_rect, mode, alpha, interpolation_mode, m_interpolation_mode,0);

			//绘制[9]
			src_block_rect = ExRectF(src_rect_b5.right, src_rect.top, src_rect.right, src_rect_b5.top);
			dst_block_rect = ExRectF(dst_rect_b5.right, dst_rect.top, dst_rect.right, dst_rect_b5.top);
			OnDrawImage(image, dst_block_rect, src_block_rect, mode, alpha, interpolation_mode, m_interpolation_mode,0);

			//绘制[1]
			src_block_rect = ExRectF(src_rect.left, src_rect_b5.bottom, src_rect_b5.left, src_rect.bottom);
			dst_block_rect = ExRectF(dst_rect.left, dst_rect_b5.bottom, dst_rect_b5.left, dst_rect.bottom);
			OnDrawImage(image, dst_block_rect, src_block_rect, mode, alpha, interpolation_mode, m_interpolation_mode,0);

			//绘制[3]
			src_block_rect = ExRectF(src_rect_b5.right, src_rect_b5.bottom, src_rect.right, src_rect.bottom);
			dst_block_rect = ExRectF(dst_rect_b5.right, dst_rect_b5.bottom, dst_rect.right, dst_rect.bottom);
			OnDrawImage(image, dst_block_rect, src_block_rect, mode, alpha, interpolation_mode, m_interpolation_mode,0);
		}

		return S_OK;
	}
	HRESULT UICanvas::DrawShadow(UIBrush *bkg_brush, float left, float top,
		float right, float bottom, float size, float radius_left_top, float radius_right_top,
		float radius_right_bottom, float radius_left_bottom, float offset_x, float offset_y)
	{
		CHECK_PARAM(bkg_brush);
		HRESULT rel = S_FALSE;
		try
		{
			UIRegion* region = new UIRegion(left, top, right, bottom,
				radius_left_top, radius_right_top,
				radius_right_bottom, radius_left_bottom);
			rel = DrawShadowFromRegion(bkg_brush, region, size, offset_x, offset_y);
			delete region;
		}
		catch_default({});
		return rel;
	}
	HRESULT UICanvas::DrawShadowFromRegion(UIBrush *bkg_brush, UIRegion *region,
		float size, float offset_x, float offset_y)
	{
		CHECK_PARAM(bkg_brush);
		CHECK_PARAM(region);

		//创建临时渲染目标
		ID2D1BitmapRenderTarget* rt;
		handle_if_failed(
			g_d2d_dc->CreateCompatibleRenderTarget(&rt),
			L"创建临时渲染目标失败"
		);

		//生成一个圆角矩形几何形
		ID2D1Geometry* src_geometry = (ID2D1Geometry*)region->GetContext();

		//填充图形
		rt->BeginDraw();
		rt->Clear();
		rt->SetTransform(D2D1::Matrix3x2F::Translation(offset_x, offset_y));
		rt->FillGeometry(src_geometry, (ID2D1Brush*)bkg_brush->GetContext());
		handle_if_failed(rt->EndDraw(), L"填充圆角矩形错误");

		//创建一个与画布一样大小的图形
		ID2D1RectangleGeometry* rect_geometry;
		handle_if_failed(g_d2d_factory->CreateRectangleGeometry(
			D2D1::RectF(0, 0, m_size.cx, m_size.cy),
			&rect_geometry
		), L"创建临时矩形几何形失败");

		//生成裁剪了中心圆角矩形的图形(ClipRegion)
		ID2D1PathGeometry* geometry;
		ID2D1GeometrySink* sink;
		handle_if_failed(
			g_d2d_factory->CreatePathGeometry(&geometry),
			L"创建剪辑区几何形失败"
		);
		handle_if_failed(geometry->Open(&sink), L"开始描述剪辑区几何形失败");

		//用大区域排除中心圆角矩形
		handle_if_failed(
			rect_geometry->CombineWithGeometry(src_geometry,
				D2D1_COMBINE_MODE_EXCLUDE, nullptr, sink
			), L"生成剪辑区几何形错误"
		);
		handle_if_failed(sink->Close(), L"生成剪辑区几何形错误");
		sink->Release();

		//获得绘制阴影的位图
		ID2D1Bitmap* bitmap;
		handle_if_failed(rt->GetBitmap(&bitmap), L"获取阴影位图失败");

		//创建模糊效果器
		ID2D1Effect* effect;
		handle_if_failed(g_d2d_dc->CreateEffect(CLSID_D2D1GaussianBlur, &effect), L"创建模糊效果器失败");

		//设置效果器参数
		effect->SetInput(0, bitmap);
		effect->SetValue(D2D1_GAUSSIANBLUR_PROP_STANDARD_DEVIATION, size / 2.0F);
		effect->SetValue(D2D1_GAUSSIANBLUR_PROP_BORDER_MODE, D2D1_BORDER_MODE_SOFT);
		effect->SetValue(D2D1_GAUSSIANBLUR_PROP_OPTIMIZATION, D2D1_DIRECTIONALBLUR_OPTIMIZATION_BALANCED);
		//设置剪辑区
		ID2D1Layer* layer;
		handle_if_failed(g_d2d_dc->CreateLayer(&layer), L"创建剪辑层失败");
		g_d2d_dc->PushLayer(
			D2D1::LayerParameters(
				D2D1::InfiniteRect(),
				geometry,
				D2D1_ANTIALIAS_MODE_PER_PRIMITIVE
			), layer
		);

		//将模糊后的阴影图绘制到画布上
		g_d2d_dc->DrawImage(effect, m_interpolation_mode);
		g_d2d_dc->PopLayer();
		bitmap->Release();
		rt->Release();
		rect_geometry->Release();
		geometry->Release();
		effect->Release();
		layer->Release();
		return S_OK;
	}
	HRESULT UICanvas::DrawCanvas(UICanvas *canvas_src, float left, float top, float right, float bottom,
		float src_left, float src_top, CanvasDrawMode mode, INT alpha, BOOL cdraw)
	{
		if (alpha == ALPHA_TRANSPARENT) { return S_FALSE; }
		CHECK_PARAM(canvas_src);
		try
		{
			//获取源图
			ID2D1Bitmap* src_bitmap = (ID2D1Bitmap*)canvas_src->GetContext(3);
			ExAssert(src_bitmap);
			//计算源、目标矩形
			D2D1_RECT_F dst = D2D1Rect(left, top, right, bottom);
			D2D1_RECT_F src = D2D1::RectF(src_left, src_top,
				src_left + fabs(dst.right - dst.left),
				src_top + fabs(dst.bottom - dst.top)
			);

			if (cdraw) { throw_if_failed(canvas_src->BeginDraw(), L"开始绘制画布失败"); }
			//混合模式
			if (mode == CanvasDrawMode::Blend) {
				g_d2d_dc->DrawBitmap(
					src_bitmap, dst, alpha / 255.0F,
					D2D1_BITMAP_INTERPOLATION_MODE_LINEAR, &src
				);
			}
			//覆盖模式
			else if (mode == CanvasDrawMode::Over) {

				//如果不是不透明的情况
				if (alpha != ALPHA_OPAQUE) {
					//先将目标区域清空
					g_d2d_dc->PushAxisAlignedClip(dst, D2D1_ANTIALIAS_MODE_PER_PRIMITIVE);
					g_d2d_dc->Clear();
					g_d2d_dc->PopAxisAlignedClip();
					
					//然后按指定透明度绘制
					g_d2d_dc->DrawBitmap(
						src_bitmap, dst, alpha / 255.0F,
						D2D1_BITMAP_INTERPOLATION_MODE_LINEAR, &src
					);
				}
				//否则直接拷贝位图
				else {

					//先刷新一下
					throw_if_failed(canvas_src->Flush(), L"刷新源画布失败");
					//直接拷贝
					D2D1_RECT_U src_u = D2D1::RectU(src.left, src.top, src.right, src.bottom);
					D2D1_POINT_2U dst_u = D2D1::Point2U(dst.left, dst.top);
					throw_if_failed(
						m_bitmap->CopyFromBitmap(&dst_u, src_bitmap, &src_u),
						L"拷贝位图失败"
					);
				}
			}
			else if (mode == CanvasDrawMode::OverBlend) {

				//FIXME:这里暂时使用AlphaBlend实现，后续可能使用蒙板实现？
				HDC src_dc = NULL;
				HDC dst_dc = NULL;
				bool ok = false;

				if (SUCCEEDED(canvas_src->GetDC(&src_dc))) {

					if (SUCCEEDED(GetDC(&dst_dc))) {
						BLENDFUNCTION bf = { 0,0,(BYTE)alpha, AC_SRC_OVER };

						ok = GdiAlphaBlend(
							dst_dc, dst.left, dst.top,
							dst.right - dst.left, dst.bottom - dst.top,
							src_dc, src.left, src.top,
							src.right - src.left, src.bottom - src.top,
							bf
						);

						this->ReleaseDC();
					}

					canvas_src->ReleaseDC();
				}

				throw_if_false(ok, E_FAIL, L"执行透明混合失败");
			}
			else { throw_ex(E_NOTIMPL, L"不支持的绘制模式"); }

			if (cdraw) { throw_if_failed(canvas_src->EndDraw(), L"绘制中出现错误"); }
			return S_OK;
		}
		catch_default({
				if (cdraw) { canvas_src->EndDraw(); }
			}
		);
	}
	HRESULT UICanvas::blur(LPVOID pBitmap, FLOAT fDeviation, RECT* lprc, FLOAT radius, BOOL fmodesoft)
	{
		ID2D1Bitmap* m_pBitmap = (ID2D1Bitmap*)pBitmap;
		if (m_pBitmap == nullptr)
			m_pBitmap = m_bitmap;
		ExAssert(m_pBitmap);
		HRESULT hr = S_FALSE;
		g_d2d_dc->Flush();
		//创建模糊效果器
		ID2D1Effect* effect;
		handle_if_failed(g_d2d_dc->CreateEffect(CLSID_D2D1GaussianBlur, &effect), L"创建模糊效果器失败");
		D2D1_SIZE_F size = {};
		D2D1_POINT_2F ptOffset = {};
		if (lprc == nullptr)
		{
			size = m_pBitmap->GetSize();
		}
		else
		{
			ptOffset.x = (FLOAT)lprc->left;
			ptOffset.y = (FLOAT)lprc->top;
			size.width = (FLOAT)lprc->right - ptOffset.x;
			size.height = (FLOAT)lprc->bottom - ptOffset.y;
		}
		ID2D1Bitmap1* pCopyBitmap;
		//创建新的渲染目标位图
		handle_if_failed(
			g_d2d_dc->CreateBitmap(
				D2D1::SizeU((INT)size.width, (INT)size.height), nullptr, 0,
				D2D1::BitmapProperties1(
					D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_GDI_COMPATIBLE,
					D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED),
					_SYS_DEFAULT_DPI, _SYS_DEFAULT_DPI, nullptr),
				&pCopyBitmap
			), L"创建渲染目标位图失败"
		);
		if (pCopyBitmap)
		{
			pCopyBitmap->CopyFromBitmap(NULL, m_pBitmap, (D2D_RECT_U*)lprc);
			effect->SetInput(0, pCopyBitmap, TRUE);
			if (fmodesoft)
				effect->SetValue(D2D1_GAUSSIANBLUR_PROP_BORDER_MODE, D2D1_BORDER_MODE_HARD);
			else
				effect->SetValue(D2D1_GAUSSIANBLUR_PROP_BORDER_MODE, D2D1_BORDER_MODE_SOFT);
			hr = effect->SetValue(D2D1_GAUSSIANBLUR_PROP_STANDARD_DEVIATION, fDeviation);
			if (SUCCEEDED(hr))
			{
				g_d2d_dc->Clear(0);
				if (radius)
				{
					ID2D1Image* soutput1;
					effect->GetOutput(&soutput1);
					ID2D1ImageBrush* hBrush = nullptr;
					g_d2d_dc->CreateImageBrush(
						soutput1,
						D2D1::ImageBrushProperties(
							D2D1::RectF(0, 0, size.width, size.height),
							D2D1_EXTEND_MODE_WRAP,
							D2D1_EXTEND_MODE_WRAP,
							D2D1_INTERPOLATION_MODE_NEAREST_NEIGHBOR
						),
						&hBrush
					);
					if (hBrush)
					{
						D2D1_ROUNDED_RECT rect = {};
						rect.rect = { 0, 0, size.width, size.height };

						rect.radiusX = radius;
						rect.radiusY = radius;
						g_d2d_dc->FillRoundedRectangle(rect, hBrush);
						hBrush->Release();
					}
					SafeRelease(soutput1);
				}
				else
				{
					g_d2d_dc->DrawImage(effect, ptOffset, D2D1_INTERPOLATION_MODE_LINEAR, D2D1_COMPOSITE_MODE_DESTINATION_OVER);
				}
			}
			SafeRelease(effect);
			SafeRelease(pCopyBitmap);
		}
		return hr;
	}
	void UICanvas::Rotate(FLOAT fAngle, FLOAT scaleX, FLOAT scaleY)
	{
		ExMatrix3x2 matrix;
		matrix.Translate((FLOAT)m_size.cx / 2, (FLOAT)m_size.cy / 2);
		matrix.Rotate(fAngle);
		if (scaleX != 0 && scaleY != 0)
			matrix.Scale(1 + scaleX, 1 + scaleY);
		matrix.Translate(-(FLOAT)m_size.cx / 2, -(FLOAT)m_size.cy / 2);
		SetTransform(&matrix);
		matrix.Reset();
	}
	IDWriteTextLayout* UICanvas::ToLayout(UIFont *font, LPCWSTR text, size_t text_length,
		ExRectF rect, DWORD text_format)
	{
		//空串则不生成
		if (text == nullptr || text_length == 0) { return nullptr; }
		if (text_length == -1 && *text == L'\0') { return nullptr; }

		IDWriteTextLayout* layout;
		HRESULT status = S_OK;

		//获得字体上下文
		auto font_s = (ExFontContextD2D*)font->GetContext(2);
		//规格化矩形
		rect = rect.Normalize();

		//最终的文本对象
		std::wstring str;
		if (text_length == -1) { str = std::wstring(text); }
		else { str = std::wstring(text, text_length); }

		//对字符串预处理,记录下所有的前缀符&,并删除对应字符
		std::list<size_t> perfix_pos_list;
		if (text_format & TextFormat::Prefix) {

			//循环查找前缀符
			size_t pos = str.find(L'&');
			while (pos != std::wstring::npos) {

				//获取它的下一个字符
				wchar_t ch = str[pos + 1];

				//删除前缀符
				str.replace(pos, 1, 0, L'\0');

				//如果下个字符不是结束符或前缀符(&&的情况),则记录下来
				if (ch != L'\0' && ch != L'&') {
					perfix_pos_list.push_back(pos);
				}
				//否则跳过
				else { pos++; }

				//继续查找
				pos = str.find(L'&', pos);
			}
		}

		//获取最大尺寸
		float w = rect.Width(), h = rect.Height();
		if (w <= 0) { w = D2D1::FloatMax(); }
		if (h <= 0) { h = D2D1::FloatMax(); }

		//创建文本布局对象
		throw_if_failed(
			g_dwrite_factory->CreateTextLayout(
				str.c_str(), (size_t)str.size(), font_s->font,
				w, h, &layout
			), L"创建字体布局对象失败"
		);

		DWRITE_TEXT_RANGE range = { 0, (size_t)str.size() };

		//处理下换线
		if (font_s->LogFont->lfUnderline) {
			status = (layout->SetUnderline(true, range));
		}
		//如果存在前缀符,且不隐藏,则给对应字符添加下划线
		else if (perfix_pos_list.size() > 0 && (text_format & TextFormat::HidePrefix) == 0) {

			DWRITE_TEXT_RANGE r = { 0,1 };
			for (auto it : perfix_pos_list) {
				r.startPosition = (size_t)it;
				status = (layout->SetUnderline(true, r));
			}

		}

		//处理删除线
		if (font_s->LogFont->lfStrikeOut) {
			status = (layout->SetStrikethrough(true, range));
		}

		//处理文本方向
		if (text_format & TextFormat::RtlReading) {
			status = (layout->SetReadingDirection(DWRITE_READING_DIRECTION_RIGHT_TO_LEFT));
		}

		if (text_format & TextFormat::Vertical) {
			layout->SetReadingDirection(DWRITE_READING_DIRECTION_TOP_TO_BOTTOM);
			layout->SetFlowDirection(DWRITE_FLOW_DIRECTION_LEFT_TO_RIGHT);
		}

		//设置文本粗细
		status = layout->SetFontWeight(
			(DWRITE_FONT_WEIGHT)font_s->LogFont->lfWeight,
			range
		);

		//处理制表符
		if (text_format & TextFormat::TabStop) {
			//指定制表位宽度
			if (text_format & TextFormat::ExpandTabs)
				status = (layout->SetIncrementalTabStop((float)((text_format >> 8) & 0xFF)));
		}
		else {
			//不展开制表位
			status = (layout->SetIncrementalTabStop(0));
		}

		//是否剪辑
		if ((text_format & TextFormat::NoClip) == 0)
		{
			layout->SetMaxWidth(rect.Width());
			layout->SetMaxHeight(rect.Height());
		}

		//设置换行模式
		layout->SetWordWrapping(
			(text_format & TextFormat::SingleLine) ?
			DWRITE_WORD_WRAPPING_NO_WRAP :
			DWRITE_WORD_WRAPPING_WRAP
		);

		//设置裁剪模式
		if (text_format & (TextFormat::PathEllipsis | TextFormat::WordEllipsis | TextFormat::EndEllipsis)) {

			IDWriteInlineObject* ellipsis;
			status = g_dwrite_factory->CreateEllipsisTrimmingSign(layout, &ellipsis);

			if (SUCCEEDED(status)) {

				DWRITE_TRIMMING trimming;

				//是否按单词裁剪
				trimming.granularity = (text_format & TextFormat::WordBreak) ?
					DWRITE_TRIMMING_GRANULARITY_WORD :
					DWRITE_TRIMMING_GRANULARITY_CHARACTER;

				//是否是按路径裁剪
				if (text_format & TextFormat::PathEllipsis) {
					trimming.delimiterCount = 2;
					trimming.delimiter = L'\\';
				}
				else {
					trimming.delimiterCount = 0;
					trimming.delimiter = 0;
				}

				//引用裁剪
				status = (layout->SetTrimming(&trimming, ellipsis));
			}
			ellipsis->Release();
		}

		//如果不是测量模式,则设置对齐模式
		if ((text_format & DT_CALCRECT) == 0) {

			status = (layout->SetTextAlignment(
				text_format & TextFormat::Center ? DWRITE_TEXT_ALIGNMENT_CENTER :
				text_format & TextFormat::Right ? DWRITE_TEXT_ALIGNMENT_TRAILING :
				DWRITE_TEXT_ALIGNMENT_LEADING
			));

			status = (layout->SetParagraphAlignment(
				text_format & TextFormat::Middle ? DWRITE_PARAGRAPH_ALIGNMENT_CENTER :
				text_format & TextFormat::Bottom ? DWRITE_PARAGRAPH_ALIGNMENT_FAR :
				DWRITE_PARAGRAPH_ALIGNMENT_NEAR
			));
		}

		return layout;
	}
	LPVOID UICanvas::GetContext(INT index)
	{
		switch (index)
		{
		case 0: return g_d2d_dc;
		case 1: return g_d2d_gdiInterop;
		case 2: return m_clip_region->GetContext();
		case 3: return m_bitmap;
		default: return nullptr;
		}
	}
}


